﻿#region Imports
using System;
using System.Windows.Forms;
using System.IO;
using WeifenLuo.WinFormsUI.Docking;
using System.Resources;
using System.Globalization;
using ScintillaNet;
using System.Threading;

#endregion

namespace VisualPureBasicIDE.CoreGUI
{
    public partial class EditorForm : DockContent
    {
        #region Fields and Properties

        private readonly Document _thisDocument;
        private readonly ResourceManager _rm;
        private readonly CultureInfo _curCulture;

        [Obsolete("This property is obsolete. Please use \"InnerDocument\" instead")]
        public string FileName
        {
            get { return _thisDocument.Path; }
        }

        public Document InnerDocument
        {
            get { return _thisDocument; }
        }
        #endregion

        #region Constructors

        /// <summary>
        /// Initializes a new formEditor
        /// </summary>
        /// <param name="document">The assigned Document instance</param>
        public EditorForm(Document document)
        {
            InitializeComponent();

            if (document == null) throw new ArgumentNullException("document");
            _rm = new ResourceManager("VisualPureBasicIDE.CoreGUI.language", typeof(EditorForm).Assembly);
            _curCulture = Thread.CurrentThread.CurrentUICulture;
            _thisDocument = document;
        }
        
        #endregion

        #region Helper procedures
        private void AddOrRemoveAsterisk()
        {
            if (scintilla.Modified) TabText = _thisDocument.Name + " *"; else TabText = _thisDocument.Name;
        }

        public bool SaveThisDocument()
        {
            try
            {
                if (File.Exists(_thisDocument.Path))
                {
                    File.WriteAllText(_thisDocument.Path, scintilla.Text);
                }
                else
                {
                    if (saveFileDialog.ShowDialog() != DialogResult.Cancel && saveFileDialog.FileName != "")
                    {
                        File.WriteAllText(saveFileDialog.FileName, scintilla.Text);
                        _thisDocument.Path = saveFileDialog.FileName;
                        var fi = new FileInfo(saveFileDialog.FileName);
                        _thisDocument.Name = fi.Name;
                    }
                    else
                    {
                        return false;
                    }
                }

                //_parent.toolStripStatusLabelAction.Text = rm.GetString("strFileSuccessfullySaved", curCulture);
                //_parent.timerResetStatusStrip.Start();
                Scintilla.Modified = false;
                return true;
            }
            catch (Exception ex)
            {
                MessageBox.Show("An error occurred while saving: '" + ex.Message + "'.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                Logger.SendException(ex);
                //_parent.toolStripStatusLabelAction.Text = rm.GetString("strErrWhileSaving", curCulture) + '"' + ex.Message + '"';
                //_parent.timerResetStatusStrip.Start();
                return false;
            }
        }

        public Scintilla Scintilla
        {
            get { return scintilla; }
        }

        private void ActivateOrDeactivateUndo()
        {
            if (scintilla.Modified && scintilla.UndoRedo.CanUndo) EventManager.OnActivateUndo(new object(), new EventArgs()); else EventManager.OnDeactivateUndo(new object(), new EventArgs());
        }  
        #endregion

        #region GUIEventProcedures
        private void tabEntfernenToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Close();
        }

        private void kopierenToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (scintilla.Selection != null) System.Windows.Forms.Clipboard.SetText(scintilla.Selection.Text);
        }

        private void einfügenToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (System.Windows.Forms.Clipboard.ContainsText()) scintilla.Selection.Text = System.Windows.Forms.Clipboard.GetText();
        }

        private void formEditor_Load(object sender, EventArgs e)
        {
            if (_thisDocument == null) throw new NullReferenceException("The document has not been specified");
            scintilla.ConfigurationManager.Language = "purebasic";
        }

        private void formEditor_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (scintilla.Modified)
            {
                var rslt = MessageBox.Show(_rm.GetString("strSaveBeforeClosingInfo", _curCulture), _rm.GetString("strSaveQuestion", _curCulture) + " (" + _thisDocument.Name + ")", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Asterisk, MessageBoxDefaultButton.Button1);
                
                switch (rslt)
                {
                    case DialogResult.Cancel:
                        e.Cancel = true;
                        return;
                    case DialogResult.Yes:
                        if (!SaveThisDocument()) e.Cancel = true;
                        break;
                }
            }

            DocumentManager.RemoveDocument(_thisDocument, false);
        }

        private void timerSetFocus_Tick(object sender, EventArgs e)
        {
            scintilla.Focus();
            timerSetFocus.Stop();
        }

        private void formEditor_Activated(object sender, EventArgs e)
        {
            // Subscribe standard actions
            EventManager.UndoLastAction += StandardActions_UndoLastAction;
            EventManager.RedoLastAction += StandardActions_RedoLastAction;
            EventManager.CopyContent += StandardActionsCopyContent;
            EventManager.CutContent += StandardActionsCutContent;
            EventManager.PasteContent += StandardActionsPasteContent;
        }

        void StandardActionsPasteContent(object sender, EventArgs e)
        {
            if (System.Windows.Forms.Clipboard.ContainsText()) scintilla.Selection.Text = System.Windows.Forms.Clipboard.GetText();
        }

        void StandardActionsCutContent(object sender, EventArgs e)
        {
            if (scintilla.Selection != null)
            {
                System.Windows.Forms.Clipboard.SetText(scintilla.Selection.Text);
                scintilla.Selection.Text = String.Empty;
            }
        }

        void StandardActionsCopyContent(object sender, EventArgs e)
        {
            if (scintilla.Selection != null) System.Windows.Forms.Clipboard.SetText(scintilla.Selection.Text);
        }

        void StandardActions_RedoLastAction(object sender, EventArgs e)
        {
            try
            { scintilla.UndoRedo.Redo(); }
            catch (Exception ex) { Logger.SendException(ex); }
            if (scintilla.UndoRedo.CanRedo == false) EventManager.OnDeactivateRedo(sender, e);
            if (scintilla.UndoRedo.CanUndo) EventManager.OnActivateUndo(sender, e);
        }

        void StandardActions_UndoLastAction(object sender, EventArgs e)
        {
            try
            { scintilla.UndoRedo.Undo(); }
            catch (Exception ex) { Logger.SendException(ex); }
            if (scintilla.UndoRedo.CanUndo == false) EventManager.OnDeactivateUndo(sender, e);
            if (scintilla.UndoRedo.CanRedo) EventManager.OnActivateRedo(sender, e);

        }

        private void formEditor_Deactivate(object sender, EventArgs e)
        {
            // Release subscriptions
            EventManager.UndoLastAction -= StandardActions_UndoLastAction;
            EventManager.RedoLastAction -= StandardActions_RedoLastAction;
            EventManager.CopyContent -= StandardActionsCopyContent;
            EventManager.CutContent -= StandardActionsCutContent;
            EventManager.PasteContent -= StandardActionsPasteContent;
        }

        private void scintilla_ModifiedChanged(object sender, EventArgs e)
        {
            if (_thisDocument.Name != null)
            {
                AddOrRemoveAsterisk();
                ActivateOrDeactivateUndo();
            }
        }
        #endregion
    }
}